using UnityEngine;

public class GyroController : MonoBehaviour
{
	private bool gyroEnabled = true;

	private const float lowPassFilterFactor = 0.2f;

	private readonly Quaternion baseIdentity = Quaternion.Euler(90f, 0f, 0f);

	private readonly Quaternion landscapeRight = Quaternion.Euler(0f, 0f, 90f);

	private readonly Quaternion landscapeLeft = Quaternion.Euler(0f, 0f, -90f);

	private readonly Quaternion upsideDown = Quaternion.Euler(0f, 0f, 180f);

	private Quaternion cameraBase = Quaternion.identity;

	private Quaternion calibration = Quaternion.identity;

	private Quaternion baseOrientation = Quaternion.Euler(90f, 0f, 0f);

	private Quaternion baseOrientationRotationFix = Quaternion.identity;

	private Quaternion referanceRotation = Quaternion.identity;

	private bool debug = true;

	protected void Start()
	{
		AttachGyro();
	}

	protected void Update()
	{
		if (gyroEnabled)
		{
			base.transform.rotation = Quaternion.Slerp(base.transform.rotation, cameraBase * (ConvertRotation(referanceRotation * Input.gyro.attitude) * GetRotFix()), 0.2f);
		}
	}

	protected void OnGUI()
	{
		if (!debug)
		{
			return;
		}
		GUILayout.Label("Orientation: " + Screen.orientation);
		GUILayout.Label("Calibration: " + calibration);
		GUILayout.Label("Camera base: " + cameraBase);
		GUILayout.Label("input.gyro.attitude: " + Input.gyro.attitude);
		GUILayout.Label("transform.rotation: " + base.transform.rotation);
		if (GUILayout.Button("On/off gyro: " + Input.gyro.enabled, GUILayout.Height(100f)))
		{
			Input.gyro.enabled = !Input.gyro.enabled;
		}
		if (GUILayout.Button("On/off gyro controller: " + gyroEnabled, GUILayout.Height(100f)))
		{
			if (gyroEnabled)
			{
				DetachGyro();
			}
			else
			{
				AttachGyro();
			}
		}
		if (GUILayout.Button("Update gyro calibration (Horizontal only)", GUILayout.Height(80f)))
		{
			UpdateCalibration(true);
		}
		if (GUILayout.Button("Update camera base rotation (Horizontal only)", GUILayout.Height(80f)))
		{
			UpdateCameraBaseRotation(true);
		}
		if (GUILayout.Button("Reset base orientation", GUILayout.Height(80f)))
		{
			ResetBaseOrientation();
		}
		if (GUILayout.Button("Reset camera rotation", GUILayout.Height(80f)))
		{
			base.transform.rotation = Quaternion.identity;
		}
	}

	private void AttachGyro()
	{
		gyroEnabled = true;
		ResetBaseOrientation();
		UpdateCalibration(true);
		UpdateCameraBaseRotation(true);
		RecalculateReferenceRotation();
	}

	private void DetachGyro()
	{
		gyroEnabled = false;
	}

	private void UpdateCalibration(bool onlyHorizontal)
	{
		if (onlyHorizontal)
		{
			Vector3 vector = Input.gyro.attitude * -Vector3.forward;
			vector.z = 0f;
			if (vector == Vector3.zero)
			{
				calibration = Quaternion.identity;
			}
			else
			{
				calibration = Quaternion.FromToRotation(baseOrientationRotationFix * Vector3.up, vector);
			}
		}
		else
		{
			calibration = Input.gyro.attitude;
		}
	}

	private void UpdateCameraBaseRotation(bool onlyHorizontal)
	{
		if (onlyHorizontal)
		{
			Vector3 forward = base.transform.forward;
			forward.y = 0f;
			if (forward == Vector3.zero)
			{
				cameraBase = Quaternion.identity;
			}
			else
			{
				cameraBase = Quaternion.FromToRotation(Vector3.forward, forward);
			}
		}
		else
		{
			cameraBase = base.transform.rotation;
		}
	}

	private static Quaternion ConvertRotation(Quaternion q)
	{
		return new Quaternion(q.x, q.y, 0f - q.z, 0f - q.w);
	}

	private Quaternion GetRotFix()
	{
		return Quaternion.identity;
	}

	private void ResetBaseOrientation()
	{
		baseOrientationRotationFix = GetRotFix();
		baseOrientation = baseOrientationRotationFix * baseIdentity;
	}

	private void RecalculateReferenceRotation()
	{
		referanceRotation = Quaternion.Inverse(baseOrientation) * Quaternion.Inverse(calibration);
	}
}
